 /* 
  *  Syntelos XB
  *  Copyright (C) 2006 John Pritchard.
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License as
  *  published by the Free Software Foundation; either version 2 of
  *  the License, or (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  *  General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  *  02111-1307 USA
  */

package syntelos.xb.op;

/**
 * <p> Child of {@link syntelos.xb.Op} for its static CF level
 * (not runtime stack) operands. </p>
 * 
 * @see syntelos.xb.at.Code
 */
public class Operand
    extends syntelos.xb.Base
    implements syntelos.xb.XB.XOP
{
    public final static syntelos.iou.dom.Name NAME = new syntelos.iou.dom.impl.Name(ELEMENT_NODE,"http://www.syntelos.org/xb/op","xop:operand");

    /**
     * <p> Child of {@link syntelos.xb.Op} for a static
     * operand. </p>
     * 
     * @see syntelos.xb.op.Ldc
     * @see syntelos.xb.op.LdcW
     * @see syntelos.xb.op.Ldc2W
     */
    public static class Constant 
	extends Operand
    {
	public final static syntelos.iou.dom.Name NAME = new syntelos.iou.dom.impl.Name(ELEMENT_NODE,"http://www.syntelos.org/xb/op","xop:operand.constant");

	public Constant(org.w3c.dom.Document doc, syntelos.iou.dom.Name name){
	    super(doc,name);
	}
	public Constant(org.w3c.dom.Document doc){
	    this(doc,NAME);
	}
	public Constant(){
	    this(DOC_NIL);
	}

	public syntelos.iou.dom.Node decompile(){
	    this.getOperandConst();
	    return this;
	}
	public syntelos.iou.dom.Node compile(){
	    this.getOperandConst();
	    return this;
	}
	public final syntelos.xb.CF.Constants.Const getOperandConst(){
	    return (syntelos.xb.CF.Constants.Const)this.getChildData(syntelos.xb.IO.Data.CONST,this);
	}
	public void setOperand(syntelos.xb.CF.Constants.Const constant){
	    this.setChildData(constant,this);
	}
    }

    /**
     * <p> Child of {@link syntelos.xb.Op} for a static
     * operand. </p>
     * 
     * @see syntelos.xb.op.Iload
     * @see syntelos.xb.op.Lload
     * @see syntelos.xb.op.Fload
     * @see syntelos.xb.op.Dload
     * @see syntelos.xb.op.Aload
     * @see syntelos.xb.op.Istore
     * @see syntelos.xb.op.Lstore
     * @see syntelos.xb.op.Fstore
     * @see syntelos.xb.op.Dstore
     * @see syntelos.xb.op.Astore
     * @see syntelos.xb.op.Iinc
     * @see syntelos.xb.op.Ret
     */
    public static class Variable
	extends Operand
    {
	public final static syntelos.iou.dom.Name NAME = new syntelos.iou.dom.impl.Name(ELEMENT_NODE,"http://www.syntelos.org/xb/op","xop:operand.variable");

	public Variable(org.w3c.dom.Document doc, syntelos.iou.dom.Name name){
	    super(doc,name);
	}
	public Variable(org.w3c.dom.Document doc){
	    this(doc,NAME);
	}
	public Variable(){
	    this(DOC_NIL);
	}

	public syntelos.iou.dom.Node decompile(){
	    this.getOperandVar();
	    return this;
	}
	public syntelos.iou.dom.Node compile(){
	    this.getOperandVar();
	    return this;
	}
	public final syntelos.xb.at.Variable getOperandVar(){
	    return (syntelos.xb.at.Variable)this.getChildData(syntelos.xb.IO.Data.VAR,this);
	}
	public void setOperand(syntelos.xb.at.Variable var){
	    this.setChildData(var,this);
	}
    }

    /**
     * <p> Child of {@link syntelos.xb.Op} for a static operand
     * represented by an {@link syntelos.xb.Op} as value. </p>
     * 
     * @see Operand$Case
     * @see syntelos.xb.op.Ifeq
     * @see syntelos.xb.op.Ifne
     * @see syntelos.xb.op.Iflt
     * @see syntelos.xb.op.Ifge
     * @see syntelos.xb.op.Ifgt
     * @see syntelos.xb.op.Ifle
     * @see syntelos.xb.op.IfIcmpeq
     * @see syntelos.xb.op.IfIcmpne
     * @see syntelos.xb.op.IfIcmplt
     * @see syntelos.xb.op.IfIcmpge
     * @see syntelos.xb.op.IfIcmpgt
     * @see syntelos.xb.op.IfIcmple
     * @see syntelos.xb.op.IfAcmpeq
     * @see syntelos.xb.op.IfAcmpne
     * @see syntelos.xb.op.Goto
     * @see syntelos.xb.op.Jsr
     */
    public static class Branch
	extends Operand
    {
	public final static syntelos.iou.dom.Name NAME = new syntelos.iou.dom.impl.Name(ELEMENT_NODE,"http://www.syntelos.org/xb/op","xop:operand.branch");

	public Branch(org.w3c.dom.Document doc, syntelos.iou.dom.Name name){
	    super(doc,name);
	}
	public Branch(org.w3c.dom.Document doc){
	    this(doc,NAME);
	}
	public Branch(){
	    this(DOC_NIL);
	}

	public syntelos.iou.dom.Node decompile(){
	    this.getOperandOp();
	    return this;
	}
	public syntelos.iou.dom.Node compile(){
	    this.getOperandOp();
	    return this;
	}
	public final syntelos.xb.Op getOperandOp(){
	    return (syntelos.xb.Op)this.getChildData(syntelos.xb.IO.Data.OP,this);
	}
	public void setOperand(syntelos.xb.Op op){
	    this.setChildData(op,this);
	}
	public void readCF(syntelos.xb.Op.Reader in)
	    throws java.io.IOException
	{
	    this.setOperand(in.readInt());
	}
	public void writeCF(syntelos.iou.bbuf out)
	{
	    out.write4(this.getOperand());
	}
    }

    /**
     * <p> Child of {@link syntelos.xb.Op} for branch operands
     * that are switch cases.  The first operand is the default case
     * offset and an Attribute of the {@link
     * syntelos.xb.Op$Switch} Element named "default". </p>
     * 
     * @see Tableswitch$Case
     * @see Lookupswitch$Case
     */
    public abstract static class Case
	extends Branch
    {
	public Case(org.w3c.dom.Document doc, syntelos.iou.dom.Name name){
	    super(doc,name);
	}
	protected syntelos.xb.Op getParentOp(){
	    return (syntelos.xb.Op)this.getParentNode();
	}
	protected int getParentPC(){
	    return this.getParentOp().getPC();
	}
	public final int getOperand(){
	    java.lang.Integer number = (java.lang.Integer)this.getChildData(syntelos.xb.IO.Data.INTEGER,this);
	    if (null != number){
		int offset = number.intValue();
		int ppc = this.getParentPC();
		return (offset - ppc);
	    }
	    else
		throw new syntelos.xb.Error.State("Missing operand.");
	}
	public final void setOperand(int value){
	    int ppc = this.getParentPC();
	    int offset = (ppc + value);
	    java.lang.Integer number = new java.lang.Integer(offset);
	    this.setChildData(number,this);
	}
    }

    public Operand(org.w3c.dom.Document doc, syntelos.iou.dom.Name name){
	super(doc,name);
    }
    public Operand(org.w3c.dom.Document doc){
	this(doc,NAME);
    }
    public Operand(){
	this(DOC_NIL);
    }

    public int getOperand(){
	java.lang.Integer number = (java.lang.Integer)this.getChildData(syntelos.xb.IO.Data.INTEGER,this);
	if (null != number)
	    return number.intValue();
	else
	    throw new syntelos.xb.Error.State("Missing operand.");
    }
    public void setOperand(int value){
	java.lang.Integer number = new java.lang.Integer(value);
	this.setChildData(number,this);
    }
    public void readCF(syntelos.xb.IO.Uri src, syntelos.xb.CF.Reader reader)
	throws java.io.IOException
    {
	throw new syntelos.xb.Error.Bug(); //(Driven by Op)
    }
    public void writeCF(syntelos.xb.IO.Uri dst, syntelos.xb.CF.Writer writer)
	throws java.io.IOException
    {
	throw new syntelos.xb.Error.Bug(); //(Driven by Op)
    }
}
